import axios from 'axios'
import { saveAs } from 'file-saver'
import JSZip from 'jszip'

export async function downloadFilesAsZip(
  fileUrls: string[],
  zipFileName = 'files.zip'
): Promise<void> {
  // 创建一个 ZIP 生成器
  const zip = new JSZip()

  // 下载文件并添加到 ZIP
  await Promise.all(
    fileUrls.map(async (url) => {
      let fileName: string
      let blob: Blob

      if (url.startsWith('blob:')) {
        // 如果 URL 是 blob 格式，直接使用
        blob = await fetch(url.substring(0, url.lastIndexOf('/'))).then((r) => r.blob())
        fileName = url.substring(url.lastIndexOf('/') + 1) // 默认文件名，可以根据需要改进
      } else {
        // 否则通过 axios 下载
        // @ts-ignore
        const response = await axios.get(url, { responseType: 'blob' })
        blob = response.data
        fileName = url.substring(url.lastIndexOf('/') + 1)
      }

      zip.file(fileName, blob)
    })
  )

  // 生成 ZIP 文件内容
  const zipBlob = await zip.generateAsync({ type: 'blob' })
  saveAs(zipBlob, zipFileName)
}

export const downloadFile = async (url: string, fileName?: string) => {
  if (!fileName) {
    fileName = url.substring(url.lastIndexOf('/') + 1)
  }

  // 检查 URL 是否为 base64 格式
  const isBase64 = url.startsWith('data:')

  if (isBase64) {
    // 提取 base64 数据
    const base64Data = url.split(',')[1]
    // 解码 base64 数据
    const byteCharacters = atob(base64Data)
    const byteNumbers = new Array(byteCharacters.length)
    for (let i = 0; i < byteCharacters.length; i++) {
      byteNumbers[i] = byteCharacters.charCodeAt(i)
    }
    const byteArray = new Uint8Array(byteNumbers)
    const blob = new Blob([byteArray], { type: 'application/octet-stream' })
    saveAs(blob, decodeURI(fileName))
  } else {
    saveAs(url, decodeURI(fileName))
  }
}

export const base64ToFile = (base64Data: string, fileName: string): string => {
  // 提取 base64 数据
  const data = base64Data.split(',')[1]
  // 解码 base64 数据
  const byteCharacters = atob(data)
  const byteNumbers = new Array(byteCharacters.length)
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i)
  }
  const byteArray = new Uint8Array(byteNumbers)
  const blob = new Blob([byteArray], { type: 'application/octet-stream' })
  return URL.createObjectURL(blob) + `/${fileName}`
}

export interface QrItem {
  url: string // 二维码内容
  text: string // 底部文字
  fileName: string // 生成文件名
}

export interface WorkerMessage {
  type: 'progress' | 'complete' | 'error'
  data: {
    processed?: number
    total?: number
    blob?: Blob
    fileName?: string
    error?: string
  }
}

export async function workerBatchGenerate(
  items: QrItem[],
  concurrency = 4,
  progress: (index: number) => void
) {
  const zip = new JSZip()
  let processedCount = 0

  const icon = new Image()
  icon.src = new URL('@/assets/images/ewm.png', import.meta.url).href
  await new Promise((resolve) => setTimeout(resolve, 500))
  const iconBitmap = await createImageBitmap(icon)

  return new Promise((resolve, reject) => {
    // 消息处理函数
    function handleWorkerMessage(e: MessageEvent<WorkerMessage>) {
      const { type, data } = e.data
      switch (type) {
        case 'progress':
          progress?.(processedCount)
          console.log(`进度: ${processedCount}/${items.length}`)
          break
        case 'complete':
          if (data.blob && data.fileName) {
            zip.file(data.fileName, data.blob)
          }
          assignNextTask(e.target as Worker)
          break
        case 'error':
          workerPool.forEach((w) => w.terminate())
          reject(data.error)
          break
      }
    }

    // 创建 Worker 池
    const workerPool = Array(concurrency)
      .fill(null)
      .map(() => {
        const worker = new Worker(new URL('./qr.worker.ts', import.meta.url), {
          type: 'module',
          name: 'qr-generator'
        })
        worker.onmessage = handleWorkerMessage
        return worker
      })

    // 任务分配逻辑
    function assignNextTask(worker: Worker) {
      if (processedCount >= items.length) {
        console.log(zip.file(/.*/).length, items.length)
        if (zip.file(/.*/).length === items.length) {
          console.log('结束')
          finalizeZip()
          return
        }
      }
      const offscreen = document.createElement('canvas').transferControlToOffscreen()
      offscreen.width = 400
      offscreen.height = 450
      const nextItem = items[processedCount]
      if (nextItem)
        worker.postMessage(
          {
            item: nextItem,
            index: processedCount,
            offscreen,
            icon: iconBitmap
          },
          [offscreen]
        )
      processedCount++
    }

    // 最终打包
    async function finalizeZip() {
      const content = await zip.generateAsync({
        type: 'blob',
        streamFiles: true
      })
      saveAs(content, 'qrcodes.zip')
      workerPool.forEach((w) => w.terminate())
      resolve(void 0)
    }

    // 初始化任务分配
    workerPool.forEach(assignNextTask)
  })
}
